voiddfs(int now, int j, bool flag)//now代表枚举了的文章长度,j代表AC自动机的下标,flag代表当前的文章是否合法 { if (now == m) { ans = (ans + flag) % MOD; return; } for (int i = 0; i < 26; i++) { int t = tr[j][i]; bool is = true; while (t) { if (cnt[t]) { dfs(now + 1, tr[j][i], true); is = false; break; } t = net[t]; } if (is) dfs(now + 1, tr[j][i], flag); } }
这个暴搜只能的20分,于是尝试优化,改成了记忆化搜索,用一个数组将之前搜过的状态存起来
intdfs(int now, int j, bool flag) { if (rec[now][j][flag]) return rec[now][j][flag]; if (now == m) return flag; int res = 0; for (int i = 0; i < 26; i++) { int t = tr[j][i]; bool is = true; while (t) { if (cnt[t]) { res = (res + dfs(now + 1, tr[j][i], true)) % MOD; is = false; break; } t = net[t]; } if (is) res = (res + dfs(now + 1, tr[j][i], flag)) % MOD; } rec [now][j][flag] = res; return res; }
#include<iostream> #include<cstdio> #include<queue> using namespace std; const int N = 1e5 + 5, MOD = 1e4 + 7;
char str[N]; int tr[N][26], net[N], cnt[N], idx, ans, n, m; int f[105][N][2]; queue<int> q;
void insert() { int p = 0; for (int i = 0; str[i]; i++) { int t = str[i] - 'A'; if (!tr[p][t]) tr[p][t] = ++idx; p = tr[p][t]; } cnt[p]++; }
void build() { for (int i = 0; i < 26; i++) if (tr[0][i]) q.push(tr[0][i]); while (!q.empty()) { int t = q.front(); q.pop(); for (int i = 0; i < 26; i++) { int p = tr[t][i]; if (!p) tr[t][i] = tr[net[t]][i]; else { net[p] = tr[net[t]][i]; q.push(p); } } } }
int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) { scanf("%s", &str); insert(); } build();//AC自动机板子,就不解释了 f[0][0][0] = 1;//初始状态 for (int i = 0; i < m; i++) { for (int j = 0; j <= idx; j++) { for (int k = 0; k < 26; k++) { bool flag = false; int p = tr[j][k]; while (p) { if (cnt[p]) { flag = true; break; } p = net[p]; }//判断下一个位置是否存在一个字典中的单词 if (flag) f[i + 1][tr[j][k]][1] = (f[i + 1][tr[j][k]][1] + f[i][j][0] + f[i][j][1]) % MOD;//如果存在,就把当前位置的所有方案加上 else //不存在 { f[i + 1][tr[j][k]][0] = (f[i + 1][tr[j][k]][0] + f[i][j][0]) % MOD;//加上不合法的方案 f[i + 1][tr[j][k]][1] = (f[i + 1][tr[j][k]][1] + f[i][j][1]) % MOD;//加上合法的方案 } } } } int ans = 0; for (int i = 0; i <= idx; i++) ans = (ans + f[m][i][1]) % MOD;//将所有方案加起来 printf("%d", ans); return 0; }